package org.origin.centre.support.utils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.*;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;

/**
 * 类转换工具
 *
 * @author ferret
 * @version 2024-05-08
 */
@SuppressWarnings("unused")
public final class ConvertUtil {

    /**
     * 将给定对象转换为Boolean值。
     *
     * @param object 可以是Boolean类型，数字类型（字符串表示），或者"true"、"false"字符串。
     * @return 如果对象是Boolean类型，直接返回该布尔值；如果是数字字符串，返回非0值表示的布尔值；如果是"true"字符串，返回true；如果是"false"字符串，返回false；如果对象为null或无法转换为布尔值，返回null。
     */
    public static Boolean getBoolean(Object object) {
        if (object == null) {
            return null;
        }
        // 如果对象本身就是Boolean类型，直接返回该对象
        if (object instanceof Boolean) {
            return (Boolean) object;
        }
        // 如果对象是数字字符串，转换为布尔值（非0为true）
        if (BasicUtil.isNumeric(object.toString())) {
            return Integer.parseInt(object.toString()) != 0;
        } else {
            // 处理"true"和"false"字符串情况
            if ("true".equals(object.toString())) {
                return true;
            }
            if ("false".equals(object.toString())) {
                return false;
            }
        }
        // 如果对象为null或无法识别为上述任何类型，返回null
        return null;
    }

    /**
     * 尝试将给定对象转换为Integer类型。
     *
     * @param object 可以是Integer类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Integer类型，直接返回该整数值；如果是Number子类，将其转换为Integer；如果是数字字符串，转换为Integer；如果对象为null或无法转换为Integer，返回null。
     */
    public static Integer getInteger(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Integer) {
            return (Integer) object;
        }

        if (object instanceof Number) {
            return ((Number) object).intValue();
        }

        // 处理"true"和"false"字符串情况
        if ("true".equals(object.toString())) {
            return 0;
        }
        if ("false".equals(object.toString())) {
            return 1;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 使用BigDecimal防止溢出，确保精确转换
            return new BigDecimal(strValue).intValueExact();
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Character类型。
     *
     * @param object 可以是Character类型，字符串（长度为1），或可以转换为单个字符的其他类型。
     * @return 如果对象是Character类型，直接返回该字符；如果是长度为1的字符串，返回其中的字符；否则，如果对象为null或无法转换为单个字符，返回null。
     */
    public static Character getCharacter(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Character) {
            return (Character) object;
        }

        if (object instanceof String strValue) {
            if (strValue.length() == 1) {
                return strValue.charAt(0);
            }
        }

        // 其他类型尝试转换为Char
        try {
            return object.toString().charAt(0);
        } catch (StringIndexOutOfBoundsException e) {
            // 对象无法转换为单个字符，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Byte类型。
     *
     * @param object 可以是Byte类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Byte类型，直接返回该字节值；如果是Number子类，将其转换为Byte；如果是数字字符串，转换为Byte；如果对象为null或无法转换为Byte，返回null。
     */
    public static Byte getByte(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Byte) {
            return (Byte) object;
        }

        if (object instanceof Number) {
            return ((Number) object).byteValue();
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 使用BigDecimal防止溢出，确保精确转换
            return new BigDecimal(strValue).byteValueExact();
        } catch (NumberFormatException | ArithmeticException e) {
            // 对象不能转换为数字，或者超过了Byte的范围，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Short类型。
     *
     * @param object 可以是Short类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Short类型，直接返回该短整数值；如果是Number子类，将其转换为Short；如果是数字字符串，转换为Short；如果对象为null或无法转换为Short，返回null。
     */
    public static Short getShort(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Short) {
            return (Short) object;
        }

        if (object instanceof Number) {
            return ((Number) object).shortValue();
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 使用BigDecimal防止溢出，确保精确转换
            return new BigDecimal(strValue).shortValueExact();
        } catch (NumberFormatException | ArithmeticException e) {
            // 对象不能转换为数字，或者超过了Short的范围，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Double类型。
     *
     * @param object 可以是Double类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Double类型，直接返回该双精度浮点数；如果是Number子类，将其转换为Double；如果是数字字符串，转换为Double；如果对象为null或无法转换为Double，返回null。
     */
    public static Double getDouble(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Double) {
            return (Double) object;
        }

        if (object instanceof Number) {
            return ((Number) object).doubleValue();
        }

        // 处理"true"和"false"字符串情况
        if ("true".equals(object.toString())) {
            return 0D;
        }
        if ("false".equals(object.toString())) {
            return 1D;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            return Double.parseDouble(strValue);
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Long类型。
     *
     * @param object 可以是Long类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Long类型，直接返回该长整数值；如果是Number子类，将其转换为Long；如果是数字字符串，转换为Long；如果对象为null或无法转换为Long，返回null。
     */
    public static Long getLong(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Long) {
            return (Long) object;
        }

        if (object instanceof Number) {
            return ((Number) object).longValue();
        }

        // 处理"true"和"false"字符串情况
        if ("true".equals(object.toString())) {
            return 0L;
        }
        if ("false".equals(object.toString())) {
            return 1L;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 使用BigDecimal防止溢出，确保精确转换
            return new BigDecimal(strValue).longValueExact();
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Float类型。
     *
     * @param object 可以是Float类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Float类型，直接返回该单精度浮点数；如果是Number子类，将其转换为Float；如果是数字字符串，转换为Float；如果对象为null或无法转换为Float，返回null。
     */
    public static Float getFloat(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Float) {
            return (Float) object;
        }

        if (object instanceof Number) {
            return ((Number) object).floatValue();
        }

        // 处理"true"和"false"字符串情况
        if ("true".equals(object.toString())) {
            return 0F;
        }
        if ("false".equals(object.toString())) {
            return 1F;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 使用BigDecimal处理可能的精度问题，然后转换为Float
            return new BigDecimal(strValue).floatValue();
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为String类型。
     *
     * @param object 要转换的对象，可以是任意类型，但null值将直接转换为null字符串。
     * @return 如果对象为非null，返回其toString()结果；如果对象为null，返回null。
     */
    public static String getString(Object object) {
        if (object == null) {
            return null;
        }

        return object.toString();
    }

    /**
     * 尝试将给定对象转换为CharSequence类型。
     *
     * @param object 可以是CharSequence子类，字符串，或其他可转换为CharSequence的类型。
     * @return 如果对象是CharSequence子类，直接返回；如果是字符串，转换为CharSequence并返回；如果对象为null，返回null。
     */
    public static java.lang.CharSequence getCharSequence(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof CharSequence) {
            return (CharSequence) object;
        }

        // 尝试将其他类型转换为CharSequence
        return object.toString();
    }

    /**
     * 尝试将给定对象转换为BigDecimal类型。
     *
     * @param object 可以是BigDecimal类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是BigDecimal类型，直接返回；如果是Number子类，将其转换为BigDecimal；如果是数字字符串，转换为BigDecimal；如果对象为null或无法转换为BigDecimal，返回null。
     */
    public static java.math.BigDecimal getBigDecimal(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof BigDecimal) {
            return (BigDecimal) object;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            return new BigDecimal(strValue);
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为BigDecimal类型。
     *
     * @param object 可以是BigDecimal类型，Number子类，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是BigDecimal类型，直接返回；如果是Number子类，将其转换为BigDecimal；如果是数字字符串，转换为BigDecimal；如果对象为null或无法转换为BigDecimal，返回null。
     */
    public static java.math.BigInteger getBigInteger(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof BigInteger) {
            return (BigInteger) object;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            return new BigInteger(strValue);
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Number类型。
     *
     * @param object 可以是Number子类，BigDecimal，BigInteger，数字字符串，或可转换为数字的字符序列。
     * @return 如果对象是Number子类，直接返回；如果是BigDecimal或BigInteger，将其转换为Number；如果是数字字符串，尝试转换为最合适的Number子类；如果对象为null或无法转换为Number，返回null。
     */
    public static java.lang.Number getNumber(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof BigDecimal) {
            return (BigDecimal) object;
        }

        if (object instanceof BigInteger) {
            return (BigInteger) object;
        }

        if (object instanceof Number) {
            return (Number) object;
        }

        try {
            String strValue = object.toString().trim();
            if (strValue.isEmpty()) {
                return null;
            }

            // 尝试按不同数字类型解析
            if (strValue.contains(".")) {
                return Double.parseDouble(strValue);
            } else {
                long longValue = Long.parseLong(strValue);
                if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
                    return (int) longValue;
                } else {
                    return longValue;
                }
            }
        } catch (NumberFormatException e) {
            // 对象不能转换为数字，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为Calendar类型。
     *
     * @param object 可以是Date类型，字符串日期（需符合预设格式），或其他可解释为日期的对象。
     * @return 如果能够成功解析对象为日期，则返回对应的Calendar实例；如果对象为null或无法转换为日期，返回null。
     * 注意：此方法使用了预设的日期格式"yyyy-MM-dd HH:mm:ss"，在实际应用中可能需要根据具体需求调整。
     */
    public static java.util.Calendar getCalendar(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Date) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime((Date) object);
            return calendar;
        }

        if (object instanceof Calendar) {
            return (Calendar) object;
        }

        if (object instanceof java.time.Duration duration) {
            // 将Duration添加到当前时间创建一个Instant
            Instant instant = Instant.now().plus(duration);
            // 将Instant转换为Date
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(Date.from(instant));
            return calendar;
        }

        if (object instanceof Number) {
            Date date = getDate(object);
            if (date != null) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                return calendar;
            }
        }

        // 如果不是支持的类型，尝试调用对象的toString方法后解析
        Date date = getDate(object);
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            return calendar;
        }
        return null;
    }

    /**
     * 尝试将给定对象转换为Date类型。
     *
     * @param object 可以是Date类型，字符串日期（需符合预设格式），或其他可解释为日期的对象。
     * @return 如果能够成功解析对象为日期，则返回对应的Date实例；如果对象为null或无法转换为日期，返回null。
     * 注意：此方法使用了预设的日期格式"yyyy-MM-dd HH:mm:ss"，在实际应用中可能需要根据具体需求调整。
     */
    public static java.util.Date getDate(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Date) {
            return (Date) object;
        }

        if (object instanceof Calendar calendar) {
            return calendar.getTime();
        }

        if (object instanceof java.time.Duration duration) {
            // 将Duration添加到当前时间创建一个Instant
            Instant instant = Instant.now().plus(duration);
            // 将Instant转换为Date
            return Date.from(instant);
        }

        // SimpleDateFormat 使用局部变量，避免线程不安全

        try {
            String string = object.toString().trim();
            int length = string.length();
            if (string.matches("^d+$")) {
                // 时间戳
                if (string.length() == 13) {
                    return new Date(Long.parseLong(string));
                }

                if (length == "yyyyMMddHHmmssSSS".length()) {
                    return new SimpleDateFormat("yyyyMMddHHmmssSSS").parse(string);
                }

                if (length == "yyyyMMddHHmmss".length()) {
                    return new SimpleDateFormat("yyyyMMddHHmmss").parse(string);
                }

                if (length == "yyyyMMdd".length()) {
                    return new SimpleDateFormat("yyyyMMdd").parse(string);
                }

                if (length == "HHmmss".length()) {
                    return new SimpleDateFormat("HHmmss").parse(string);
                }

            } else {

                if (length == "yyyy-MM-dd:HH:mm:ss.SSS".length()) {
                    return new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss.SSS").parse(string);
                }

                if (length == "yyyy-MM-dd:HH:mm:ss".length()) {
                    return new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss").parse(string);
                }

                if (length == "yyyy-MM-dd".length()) {
                    return new SimpleDateFormat("yyyy-MM-dd").parse(string);
                }

                if (length == "HH:mm:ss".length()) {
                    return new SimpleDateFormat("HH:mm:ss").parse(string);
                }

                if (length == "HH:mm:ss.SSS".length()) {
                    return new SimpleDateFormat("HH:mm:ss.SSS").parse(string);
                }

                if (string.contains("T") && string.contains("Z")) {
                    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(string);
                }

            }
        } catch (ParseException e) {
            // 对象转换为字符串后仍无法解析为日期，返回null
            return null;
        }
        return null;
    }

    /**
     * 尝试将给定对象转换为Duration类型。
     *
     * @param object 可以是Duration实例，Long类型（代表毫秒数），字符串（格式如"PT1H3M"，遵循ISO-8601标准）。
     * @return 如果能够成功解析对象为Duration，则返回对应的Duration实例；如果对象为null或无法转换为Duration，返回null。
     * 注意：字符串格式应遵循ISO-8601标准，例如"PT1H3M"表示1小时3分钟。
     */
    public static Duration getDuration(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof Duration) {
            return (Duration) object;
        }

        if (object instanceof Date date) {
            return Duration.ofMillis(date.getTime());
        }

        if (object instanceof Number) {
            Date date = getDate(object);
            if (date != null) {
                return Duration.ofMillis(date.getTime());
            }
        }

        if (object instanceof String) {
            String string = object.toString();
            if (string.matches("^d+$")) {
                Date date = getDate(object);
                if (date != null) {
                    return Duration.ofMillis(date.getTime());
                }
            } else {
                try {
                    return Duration.parse(string);
                } catch (IllegalArgumentException e) {
                    Date date = getDate(object);
                    if (date != null) {
                        return Duration.ofMillis(date.getTime());
                    }
                }
            }
        }
        return null;
    }

    /**
     * 尝试将给定对象转换为java.sql.Date类型。
     *
     * @param object 可以是java.sql.Date类型，java.util.Date类型，字符串日期（需符合预设格式），或其他可解释为日期的对象。
     * @return 如果能够成功解析对象为日期，则返回对应的java.sql.Date实例；如果对象为null或无法转换为日期，返回null。
     * 注意：此方法使用了预设的日期格式"yyyy-MM-dd"，在实际应用中可能需要根据具体需求调整。
     */
    public static java.sql.Date getSqlDate(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof java.sql.Date) {
            return (java.sql.Date) object;
        }

        if (object instanceof Date) {
            return new java.sql.Date(((Date) object).getTime());
        }

        Date date = getDate(object);
        if (date != null) {
            return new java.sql.Date(date.getTime());
        }
        return null;
    }

    /**
     * 尝试将给定对象转换为java.sql.Time类型。
     *
     * @param object 可以是java.sql.Time类型，java.util.Date类型，字符串时间（需符合预设格式），或其他可解释为时间的对象。
     * @return 如果能够成功解析对象为时间，则返回对应的java.sql.Time实例；如果对象为null或无法转换为时间，返回null。
     * 注意：此方法使用了预设的时间格式"HH:mm:ss"，在实际应用中可能需要根据具体需求调整。
     */
    public static java.sql.Time getSqlTime(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof java.sql.Time) {
            return (java.sql.Time) object;
        }

        if (object instanceof Date) {
            return new Time(((Date) object).getTime());
        }

        Date date = getDate(object);
        if (date != null) {
            return new Time(date.getTime());
        }
        return null;
    }

    /**
     * 尝试将给定对象转换为java.net.URI类型。
     *
     * @param object 可以是URI实例，字符串形式的URI。
     * @return 如果能够成功解析对象为URI，则返回对应的URI实例；如果对象为null或无法转换为URI，返回null。
     */
    public static URI getURI(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof URI) {
            return (URI) object;
        }

        if (object instanceof String) {
            try {
                return new URI((String) object);
            } catch (URISyntaxException e) {
                // 解析失败，可能是URI格式不正确
                return null;
            }
        }

        // 如果不是支持的类型，尝试调用对象的toString方法后解析
        try {
            return new URI(object.toString());
        } catch (URISyntaxException e) {
            // 对象转换为字符串后仍无法解析为URI，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为java.net.URL类型。
     *
     * @param object 可以是URL实例，字符串形式的URL。
     * @return 如果能够成功解析对象为URL，则返回对应的URL实例；如果对象为null或无法转换为URL，返回null。
     */
    public static URL getURL(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof URL) {
            return (URL) object;
        }

        if (object instanceof String) {
            try {
                return new URL((String) object);
            } catch (MalformedURLException e) {
                // 解析失败，可能是URL格式不正确
                return null;
            }
        }

        // 如果不是支持的类型，尝试调用对象的toString方法后解析
        try {
            return new URL(object.toString());
        } catch (MalformedURLException e) {
            // 对象转换为字符串后仍无法解析为URL，返回null
            return null;
        }
    }

    /**
     * 尝试将给定对象转换为java.net.InetAddress类型。
     *
     * @param object 可以是InetAddress实例，字符串形式的IP地址。
     * @return 如果能够成功解析对象为InetAddress，则返回对应的InetAddress实例；如果对象为null或无法转换为InetAddress，返回null。
     */
    public static InetAddress getInetAddress(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof InetAddress) {
            return (InetAddress) object;
        }

        if (object instanceof String) {
            try {
                return InetAddress.getByName((String) object);
            } catch (UnknownHostException e) {
                // 解析失败，可能是IP地址格式不正确
                return null;
            }
        }

        // 如果不是支持的类型，尝试调用对象的toString方法后解析
        try {
            return InetAddress.getByName(object.toString());
        } catch (UnknownHostException e) {
            // 对象转换为字符串后仍无法解析为InetAddress，返回null
            return null;
        }
    }

}
